class Poster {
	constructor() {
		// 原始属性定义
		this.config = {
			canvasId: '',
			width: 0,
			height: 0,
			padding: 0,
			background: '#ffffff',
			title: '',
			logo: '',
			code: '',
			tips: '',
			data: [],
			winWidth: '',
			winHeight: '',
		}
	}
	// 设置全局默认配置
	setConfig(customConfig={}) {
		// 深度合并对象，否则会造成对象深层属性丢失
		this.config = uni.$u.deepMerge(this.config, customConfig);
		if(customConfig.padding) {
			this.config.padding = this.normalizeCssArray(customConfig.padding)
		}
		this.config.winWidth = this.config.width - this.config.padding[1] - this.config.padding[3]
		this.config.winHeight =  this.config.height - this.config.padding[0] - this.config.padding[2]
		console.log('Poster setConfig完成：',this.config)
	}
	/**
	 * 绘制分享海报 
	 * @param canvasId 
	 * @param winWidth 宽度
	 * @param winHeight 高度
	 * @param imgs 主图以及二维码图
	 *  格式 {mainPic: mainPic,qrcode: qrcode}
	 * @param text 描述文字
	 * @param name 程序名称
	 **/
	drawPoster(options = {}, callback, _this) {
		console.log('Poster 绘制开始！')
		var that = this;
		//合并用户的配置和内部的默认配置
		this.setConfig(options)
		//获取绘图上下文 context
		let context = uni.createCanvasContext(this.config.canvasId, _this)
		this.config.context = context
		this.config.coord = { x:0, y:0 }
		//海报背景
		context.setFillStyle(this.config.background);
		context.fillRect(0, 0, this.config.width, this.config.height);
		context.save();
		this.config.logo && this.config.title && this.drawPosterTitle()
		this.drawPosterGrid()
		this.config.code && this.config.tips && this.drawPosterCode()
		context.draw(false,  setTimeout(()=>{
			console.log('Poster draw绘制完成！')
			that.createPoster(this.config.canvasId, this.config.width, this.config.height, (res) => {
				callback && callback(res)
			},_this)
		},300))
	}
	//绘制海报顶部标题
	drawPosterTitle(){
		let ctxt = this.config.context
		ctxt.setFontSize(50)
		ctxt.setFillStyle("#333333")
		let logo_w = 190
		let title_w = ctxt.measureText(this.config.title).width
		title_w = title_w>(this.config.winWidth-logo_w-40) ? (this.config.winWidth-logo_w-40-200) : title_w
		let spare = this.config.winWidth - (title_w + logo_w + 40)
		let x = this.config.coord.x + spare/2 + this.config.padding[3]
		let y = this.config.coord.y + this.config.padding[0]
		this.clipCircleImg(ctxt, x, y, logo_w/2, this.config.logo)
		x = x + logo_w + 40
		y = y + (logo_w - 50)/2
		this.fillTextCut(ctxt, this.config.title, 50, 50, x, y, title_w, 1)
		this.config.coord = {x:this.config.padding[3], y:this.config.padding[0] + logo_w}
		console.log('Poster 绘制标题完成！')
	}
	//绘制海报中间课表（日期和时间表格）
	drawPosterGrid(){
		let ctxt = this.config.context
		let time = this.config.data.time
		let date = this.config.data.date
		let schedule = this.config.data.schedule
		let x = this.config.coord.x
		let y = this.config.coord.y
		y = y + 45
		let time_width = 110
		let date_height = 200
		let space_w = parseInt((this.config.winWidth-time_width)/date.length);
		let space_h = parseInt(space_w*1.05);
		//row：最左侧表格竖线
		ctxt.moveTo(x, y)
		ctxt.lineTo(x, y + date_height + space_h*time.length)
		//row：最右侧表格竖线
		ctxt.moveTo(x + space_w*date.length + time_width, y)
		ctxt.lineTo(x + space_w*date.length + time_width, y + date_height + space_h*time.length)
		//col：最顶部表格横线
		ctxt.moveTo(x, y)
		ctxt.lineTo(x + this.config.winWidth, y)
		//col：最底部表格横线
		ctxt.moveTo(x, y + date_height + space_h*time.length)
		ctxt.lineTo(x + this.config.winWidth, y + date_height + space_h*time.length)
		ctxt.setStrokeStyle('#e1e1e1')
		ctxt.stroke();
		//row：表格日期标题
		let year = new Date().getFullYear()
		let today = Public_Now()
		for (var d = 0; d < date.length; d++) {
			let d_x = x + space_w*d + time_width
			let day = year +'/'+ date[d].date.replace('.', '/');
			if (dealDateToUnix(day) < dealDateToUnix(today)) {
				ctxt.setFillStyle("#999")
			} else if (dealDateToUnix(day) == dealDateToUnix(today)) {
				this.clipCircleRect(ctxt, d_x+((space_w-140)/2), y+25, 70, '#3cc9a6')
				ctxt.setFillStyle("#fff")
			} else {
				ctxt.setFillStyle("#3cc9a6")
			}
			this.fillTextCut(ctxt, date[d].date, 24, 24, d_x, y+60, space_w, 1, true)
			this.fillTextCut(ctxt, date[d].week_name, 40, 40, d_x, y+105, space_w, 1, true)
			ctxt.moveTo(x + space_w*d + time_width, y + date_height)
			ctxt.lineTo(x + space_w*d + time_width, y + date_height + space_h*time.length)
			ctxt.setStrokeStyle('#e1e1e1')
			ctxt.stroke();
			//col：表格时间标题
			ctxt.setFillStyle("#333")
			for (var t = 0; t < time.length; t++) {
				if (d==0) {
					let t_y = y + date_height + space_h*t + (space_h-24)/2
					ctxt.moveTo(x, y + date_height + space_h*t)
					ctxt.lineTo(x + this.config.winWidth, y + date_height + space_h*t)
					ctxt.setStrokeStyle('#e1e1e1')
					ctxt.stroke();
					this.fillTextCut(ctxt, time[t].start_time, 24, 24, x, t_y, time_width, 1, true)
				}
				for (var s = 0; s < schedule.length; s++) {
					if (time[t].start_time==schedule[s].start_time && date[d].date==schedule[s].date_text) {
						let s_x = x + space_w*d + time_width
						let s_y = y + date_height + space_h*t
						this.drawPosterCard(s, s_x, s_y)
					}
				}
			}
		}
		this.config.coord = {x:this.config.padding[3], y:y + date_height + space_h*time.length}
		console.log('Poster 绘制表格完成！')
		function dealDateToUnix(time) {
			if (time !== null) {
				return new Date(time).getTime()
			}
			return false
		}
		//当前日期
		function Public_Now(){
			var now = new Date(),
			y = now.getFullYear(),
			m = now.getMonth() + 1,
			d = now.getDate();
			m = (m < 10 ? "0" + m : m).toString();
			d = (d < 10 ? "0" + d : d).toString();
			return y + "/" + m + "/" + d;
		}
	}
	//绘制海报中间课表（课表分布）
	drawPosterCard(_i, _x, _y){
		let ctxt = this.config.context
		let time = this.config.data.time
		let date = this.config.data.date
		let schedule = this.config.data.schedule
		let x = _x
		let y = _y
		let time_width = 110
		let date_height = 200
		let space_w = parseInt((this.config.winWidth-time_width)/date.length);
		let space_h = parseInt(space_w*1.05);
		let card_w = space_w - 28
		let card_h = space_h - 28
		let card_t = (card_h - 54*5)/2
		card_t = card_t>0?card_t:0
		x = x + 14
		y = y + 14
		this.clipRoundRect(ctxt, x, y, card_w, card_h, 10, schedule[_i].course.course_color.style)
		ctxt.setFillStyle("#fff")
		x = x + 20
		y = y + card_t + (54 - 36)
		this.fillTextCut(ctxt, schedule[_i].course.name, 36, 54, x, y, card_w - 40, 1, true)
		let str_time = schedule[_i].start_time +'-'+ schedule[_i].end_time
		this.fillTextCut(ctxt, str_time, 36, 54, x, y + 54, card_w - 40, 1, true)
		this.fillTextCut(ctxt, schedule[_i].teacher.name, 36, 54, x, y + 54*2, card_w - 40, 1, true)
		this.fillTextCut(ctxt, schedule[_i].classroom.name, 36, 54, x, y + 54*3, card_w - 40, 1, true)
		let star = '★★★★★'.substring(0,schedule[_i].course.degree)+'☆☆☆☆☆'.substring(schedule[_i].course.degree);
		this.fillTextCut(ctxt, star, 36, 54, x, y + 54*4, card_w - 40, 1, true)
		console.log('Poster 绘制课表完成！当前：'+_i)
	}
	//绘制海报底部二维码
	drawPosterCode(){
		let ctxt = this.config.context
		let x = this.config.coord.x
		let y = this.config.coord.y
		x = this.config.winWidth - 320 - 445
		y = y + 35
		this.clipRoundImg(ctxt, x, y, 445, 445, 0, this.config.code)
		x = x + 445 + 35
		y = y + 180
		ctxt.setFillStyle("#999")
		this.fillTextCut(ctxt, this.config.tips, 36, 45, x, y, 250, 2, true)
		console.log('Poster 绘制二维码完成！')
	}
	//生成海报图片(分享所需图片)
	createPoster(canvasId, winWidth, winHeight, callback, _this) {
		var that = this;
		// let scaleRatio= uni.getSystemInfoSync().scaleRatio
		uni.canvasToTempFilePath({
			x: 0,
			y: 0,
			width: winWidth,
			height: winHeight,
			destWidth: winWidth,
			destHeight: winHeight,
			canvasId: canvasId,
			fileType: 'png',
			quality: 1,
			success: function(res) {
				callback && callback(res.tempFilePath)
				console.log('Poster 绘制完成-生成图片成功！')
			},
			fail() {
				callback && callback(false)
				console.log('Poster 绘制完成-生成图片失败！')
			}
		},_this)
	}
	//图片转成本地文件[同步执行]
	async getImage(url) {
		return await new Promise((resolve, reject) => {
			uni.downloadFile({
				url: url,
				success: res => {
					resolve(res.tempFilePath);
					console.log('getImage 转成本地文件成功！',res)
				},
				fail: res => {
					reject(false)
					console.log('getImage 转成本地文件失败！',res)
				}
			})
		})
	}
	//删除已缓存文件，防止超出存储空间大小限制[同步执行]
	async removeSavedFile() {
		//使用前请先查看支持平台（其他方案：也可以先渲染出图片，当图片加载完成时执行相关方法）
		let count = 0;
		return await new Promise((resolve, reject) => {
			uni.getSavedFileList({
				success(res) {
					console.log('removeSavedFile 已缓存文件：',res)
					count = res.fileList.length;
					if (count > 0) {
						let num = 0;
						let list = res.fileList || []
						list.forEach(item => {
							console.log("执行删除文件。。。")
							uni.removeSavedFile({
								filePath: item.filePath,
								complete(res) {
									num++;
									if (num === count) {
										resolve(true)
									}
								}
							})
						})
					} else {
						resolve(true)
					}
				},
				fail() {
					reject(false)
					console.log("执行删除文件失败")
				}
			})
		})
	}
	/**
	 *
	 * @param {number|array} val  padding
	 */
	normalizeCssArray(val) {
		if (typeof (val) === 'number') {
			return [val, val, val, val];
		}
		var len = val.length;
		if (len === 2) {
			return [val[0], val[1], val[0], val[1]];
		}
		else if (len === 3) {
			return [val[0], val[1], val[2], val[1]];
		}
		return val;
	}
	/**
	 *
	 * @param {CanvasContext} ctx canvas上下文
	 * @param {string} text       文本的内容
	 * @param {number} fontsize   文本的字体大小
	 * @param {number} lineheight 文本的字体行高
	 * @param {number} x          文本左上角 x坐标
	 * @param {number} y          文本左上角 y坐标
	 * @param {number} width      文本的显示宽度
	 * @param {number} line       文本的显示行数（超出会省略）
	 * @param {Boolean}center     文本是否居中显示
	 */
	fillTextCut(ctx, text, fontsize, lineheight, x, y, width, line, center) {
	    var chr = text.split(''); //这个方法是将一个字符串分割成字符串数组
	    var temp = "";
	    var row = [];
	    ctx.setFontSize(fontsize)
	    ctx.setTextBaseline('top'); // 文字顶部对齐，便于计算文字到顶部距离
	    for (var a = 0; a < chr.length; a++) {
	        if (ctx.measureText(temp).width < width) {
	            temp += chr[a];
	        } else {
	            a--; //这里添加了a-- 是为了防止字符丢失
	            row.push(temp);
	            temp = '';
	        }
	    }
	    row.push(temp);
	    if (row.length > line) {
	        var rowCut = row.slice(0, line);
	        var rowPart = rowCut[line - 1];
	        var test = '';
	        var empty = [];
	        for (var a = 0; a < rowPart.length; a++) {
	            if (ctx.measureText(test).width < (width - fontsize)) {
	                test += rowPart[a];
	            } else {
	                break;
	            }
	        }
	        empty.push(test);
	        var group = empty[0] + "..." //超出的用...表示
	        rowCut.splice(line - 1, 1, group);
	        row = rowCut;
	    }
	    for (var b = 0; b < row.length; b++) {
	        if (center) x = x + (width - ctx.measureText(row[b]).width) * 0.5;
	        ctx.fillText(row[b], x, y + b * lineheight, width);
	    }
	    ctx.save();
	}
	/**
	 *
	 * @param {CanvasContext} ctx canvas上下文
	 * @param {number} x 圆角矩形选区的左上角 x坐标
	 * @param {number} y 圆角矩形选区的左上角 y坐标
	 * @param {number} r 圆角的半径
	 * @param {string} c 绘制的颜色
	 */
	clipCircleRect(ctx, x, y, r, c = '#fff') {
	    var d = 2 * r;
	    var cx = x + r;
	    var cy = y + r;
	    ctx.save()
	    ctx.fillRect(0, 0, 0, 0) // 临时性解决多次clip出现bug问题，https://developers.weixin.qq.com/community/develop/doc/000e463db405e0d0f6c61a13356000
	    ctx.beginPath() //开始绘制
	    ctx.arc(cx, cy, r, 0, 2 * Math.PI, false)
	    ctx.closePath()
	    ctx.setFillStyle(c)
	    ctx.fill()
	    ctx.restore()
	}
	/**
	 *
	 * @param {CanvasContext} ctx canvas上下文
	 * @param {number} x   圆角矩形选区的左上角 x坐标
	 * @param {number} y   圆角矩形选区的左上角 y坐标
	 * @param {number} r   圆角的半径
	 * @param {string} img 绘制的图片地址
	 */
	clipCircleImg(ctx, x, y, r, img) {
	    var d = 2 * r;
	    var cx = x + r;
	    var cy = y + r;
	    ctx.save()
	    ctx.fillRect(0, 0, 0, 0) // 临时性解决多次clip出现bug问题，https://developers.weixin.qq.com/community/develop/doc/000e463db405e0d0f6c61a13356000
	    ctx.beginPath() //开始绘制
	    ctx.arc(cx, cy, r, 0, 2 * Math.PI, false)
	    ctx.closePath()
	    ctx.clip()
	    ctx.drawImage(img, x, y, d, d)
	    ctx.restore()
	}
	/**
	 *
	 * @param {CanvasContext} ctx canvas上下文
	 * @param {number} x 圆角矩形选区的左上角 x坐标
	 * @param {number} y 圆角矩形选区的左上角 y坐标
	 * @param {number} w 圆角矩形选区的宽度
	 * @param {number} h 圆角矩形选区的高度
	 * @param {number} r 圆角的半径
	 * @param {string} c 绘制的颜色
	 */
	clipRoundRect(ctx, x, y, w, h, r, c = '#fff') {
	    ctx.save()
	    ctx.fillRect(0, 0, 0, 0) // 临时性解决多次clip出现bug问题，https://developers.weixin.qq.com/community/develop/doc/000e463db405e0d0f6c61a13356000
	    // 开始绘制
	    ctx.beginPath()
	    // 左上角
	    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
	    // border-top
	    ctx.moveTo(x + r, y)
	    ctx.lineTo(x + w - r, y)
	    ctx.lineTo(x + w, y + r)
	    // 右上角
	    ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
	    // border-right
	    ctx.lineTo(x + w, y + h - r)
	    ctx.lineTo(x + w - r, y + h)
	    // 右下角
	    ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
	    // border-bottom
	    ctx.lineTo(x + r, y + h)
	    ctx.lineTo(x, y + h - r)
	    // 左下角
	    ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
	    // border-left
	    ctx.lineTo(x, y + r)
	    ctx.lineTo(x + r, y)
	    // 因为边缘描边存在锯齿，最好指定使用 transparent 填充
	    // 这里是使用 fill 还是 stroke都可以，二选一即可
	    // ctx.setStrokeStyle('transparent')
	    ctx.setFillStyle(c)
	    // 这里是使用 fill 还是 stroke都可以，二选一即可，但是需要与上面对应
	    ctx.fill()
	    // ctx.stroke()
	    ctx.closePath()
	    // 剪切
	    ctx.clip()
	    ctx.restore()
	}
	/**
	 *
	 * @param {CanvasContext} ctx canvas上下文
	 * @param {number} x   圆角矩形选区的左上角 x坐标
	 * @param {number} y   圆角矩形选区的左上角 y坐标
	 * @param {number} w   圆角矩形选区的宽度
	 * @param {number} h   圆角矩形选区的高度
	 * @param {number} r   圆角的半径
	 * @param {string} img 绘制的图片地址
	 */
	clipRoundImg(ctx, x, y, w, h, r, img) {
	    ctx.save()
	    ctx.fillRect(0, 0, 0, 0) // 临时性解决多次clip出现bug问题，https://developers.weixin.qq.com/community/develop/doc/000e463db405e0d0f6c61a13356000
	    // 开始绘制
	    ctx.beginPath()
	    // 左上角
	    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
	    // border-top
	    ctx.moveTo(x + r, y)
	    ctx.lineTo(x + w - r, y)
	    ctx.lineTo(x + w, y + r)
	    // 右上角
	    ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
	    // border-right
	    ctx.lineTo(x + w, y + h - r)
	    ctx.lineTo(x + w - r, y + h)
	    // 右下角
	    ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
	    // border-bottom
	    ctx.lineTo(x + r, y + h)
	    ctx.lineTo(x, y + h - r)
	    // 左下角
	    ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
	    // border-left
	    ctx.lineTo(x, y + r)
	    ctx.lineTo(x + r, y)
	    ctx.closePath()
	    // 剪切
	    ctx.clip()
	    ctx.drawImage(img, x, y, w, h)
	    ctx.restore()
	}
}
export default new Poster